package cn.tao.user.service.impl;

import cn.tao.base.constant.WxConstants;
import cn.tao.base.exception.BusinessException;
import cn.tao.user.domain.LoginInfo;
import cn.tao.user.domain.User;
import cn.tao.user.domain.WxUser;
import cn.tao.user.mapper.LoginInfoMapper;
import cn.tao.user.mapper.UserMapper;
import cn.tao.user.mapper.WxUserMapper;
import cn.tao.user.service.IWxUserService;
import cn.tao.utils.AjaxResult;
import cn.tao.utils.HttpClientUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mysql.jdbc.StringUtils;
import com.sun.org.apache.bcel.internal.classfile.Code;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WxUserServiceImpl implements IWxUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private LoginInfoMapper loginInfoMapper;

    /**
     * 微信扫码登录
     * @param map
     * @return
     */
    @Override
    public AjaxResult wxlogin(Map<String, String> map) {
        //从map中拿出code，也就是前端返回的code用来再这进行发送请求，获取aseccss_token
        String code = map.get("code");
        //从常量类中拿出地址，对关键字段进行替换
        String url = WxConstants.SECCSS_TOKEN_URL
                .replace("APPID",WxConstants.APPID)
                .replace("SECRET",WxConstants.SECRET)
                .replace("CODE",code);
        //工具类获得的url地址，返回json格式的字符串
        String result = HttpClientUtils.httpGet(url);
        /*
        { result:{"access_token":"54_QPPEkvU46VbWH_4Qvy9XQrsf47uP3XqkOCdrIhvmpdZigwbJwaKQI0Zl3bv526z8Z1snUt3JUjscm-jCDlFy5QzaymUBAwmWHJtyy9xypJo","expires_in":7200,"refresh_token":"54_zrz3ALiE3xeuIi0VHZHL6l550o7_-v6sYcXuXvp741PZxMBTwJojADTUG6nk6L7OMFCfkX3l-_9ssKBZ-pvkRht8CPgkMutCW8M2Dp9mfNs","openid":"oa9wA0y-PJja8COVs3p8hi9XHfXs","scope":"snsapi_login","unionid":"ovnCWw34ZiduI7Lw3NZCo2hA_MW4"}
            通过json格式化之后：
        接口调用凭证:"access_token":  "54_QPPEkvU46VbWH_4Qvy9XQrsf47uP3XqkOCdrIhvmpdZigwbJwaKQI0Zl3bv526z8Z1snUt3JUjscm-jCDlFy5QzaymUBAwmWHJtyy9xypJo",
        接口调用凭证超时时间，单位（秒）:   "expires_in": 7200,
        用户刷新access_token:"refresh_token":   "54_zrz3ALiE3xeuIi0VHZHL6l550o7_-v6sYcXuXvp741PZxMBTwJojADTUG6nk6L7OMFCfkX3l-_9ssKBZ-pvkRht8CPgkMutCW8M2Dp9mfNs",
        授权用户唯一标识:"openid":  "oa9wA0y-PJja8COVs3p8hi9XHfXs",
        用户授权的作用域，使用逗号（,）分隔: "scope": "snsapi_login",
        当且仅当该网站应用已获得该用户的userinfo授权时，才会出现该字段。:   "unionid": "ovnCWw34ZiduI7Lw3NZCo2hA_MW4"
           }
         */
        //格式化json
        JSONObject jsonObject = JSON.parseObject(result);
        //取出access_token
        String access_token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");

        /*
        判断新老用户登录
         */
        //根据openid查询微信用户
        WxUser wxUser = wxUserMapper.loadByOpenId(openid);
        if (wxUser!=null){//老用户
            //微信用户关联的用户表
            User user = userMapper.loadById(wxUser.getUser_id());
            //用户关联的登录信息表
            LoginInfo loginInfo = loginInfoMapper.loadById(user.getLogininfo_id());
            return noPsdLogin(loginInfo);
        }else { //新用户
            //新用户，跳转到绑定页面，携带access_token,和openid到前端，再从前端发送请求回到后端
            String redirectUri="/binder.html?access_token="+access_token+"&openid="+openid;
            return AjaxResult.me().setSuccess(false).setResultObj(redirectUri);
        }
    }

    /**
     * 新用户绑定
     * @param map
     * @return
     */
    @Override
    @Transactional
    public AjaxResult bind(Map<String, String> map) {
        String phone = map.get("phone");
        String codeType = map.get("codeType");
        String code = map.get("code");
        String access_token = map.get("access_token");
        String openid = map.get("openid");

        //5.验证码是否正确
        String codeInRedis = (String) redisTemplate.opsForValue().get(phone + ":" + codeType);
        //把验证码取出来
        //2.验证码不能为空
        if (codeInRedis==null){
            return AjaxResult.me().setMessage("验证码错误");
        }
        if (!codeInRedis.split(":")[0].equals(code)){
            return AjaxResult.me().setMessage("验证码错误");
        }
        //1.获取微信的个人信息
        String url = WxConstants.WXUSER_INFO.replace("ACCESS_TOKEN",access_token)
                .replace("OPPENID",openid);
        String result = HttpClientUtils.httpGet(url);
        JSONObject jsonObject = JSON.parseObject(result);
        //生成一个新的微信用户
        System.out.println(jsonObject);
        WxUser wxUser = new WxUser();
        wxUser.setOpenid(jsonObject.getString("openid"));
        wxUser.setNickname(jsonObject.getString("nickname"));
        wxUser.setSex(jsonObject.getInteger("sex"));
        wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxUser.setUnionid(jsonObject.getString("unionid"));
        //根据电话查询用户是否注册过
        User user = userMapper.loadByPhone(phone);
        LoginInfo loginInfo = null;  //令其为空，直接在user中赋值
        if (user==null){//生成一个user对象，保存user根login info表数据
            user = new User();
            user.setUsername(jsonObject.getString("nickname"));
            user.setCreatetime(new Date());
            user.setPhone(phone);
            user.setState(1);
            user.setHeadImg(jsonObject.getString("headimgurl"));
            loginInfo = new LoginInfo();
            BeanUtils.copyProperties(user,loginInfo);
            loginInfo.setType(1);
            loginInfo.setDisable(1);

            loginInfoMapper.save(loginInfo);
            user.setLogininfo_id(loginInfo.getId());
            userMapper.save(user);

        }else {//获取用户对应的logininfo
            loginInfo = loginInfoMapper.loadById(user.getLogininfo_id());
        }

        wxUser.setUser_id(user.getId());
        wxUserMapper.save(wxUser);
        System.out.println("1111"+wxUser);
        return noPsdLogin(loginInfo);
    }

    //免密登录
    private AjaxResult noPsdLogin(LoginInfo loginInfo) {
        //获取token
        String token = UUID.randomUUID().toString();
        //把token当作key 用户login当作value 设置过期时间30分钟
        //此时启动有问题 报错  问题：redis存储数据时的序列化原因 解决：Baesdomain实现一个serializable
        redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
        //把token和loginInfo返回给前端
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("token",token);
        //把密码和盐清空
        loginInfo.setPassword("");
        loginInfo.setSalt("");
        map.put("loginInfo",loginInfo);
        return AjaxResult.me().setResultObj(map);
    }
}
